package com.gitee.mp.core.interceptor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.gitee.mp.domain.definition.FieldDefinition;
import com.gitee.mp.extend.SimilaritySetter;
import com.gitee.mp.infra.constants.MilvusPlusConstants;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 结果集映射处理
 *
 * @author hongda.li
 */
public class ResultMappingInterceptor extends AbstractMapperInterceptor {

    @Override
    public int order() {
        return Integer.MAX_VALUE - 100;
    }

    @Override
    public boolean supported(Method method) {
        return MilvusPlusConstants.MethodName.METHOD_SELECT.equals(method.getName());
    }

    @Override
    public void intercept(InterceptorContext context) {
        Class<?> entity = context.getEntity();
        Class<?> returnType = context.getMethod().getReturnType();

        Assert.isTrue(List.class.equals(returnType), "Illegal return type");

        List<?> result = (List<?>) context.getResult();

        // 空返回值
        if (CollectionUtils.isEmpty(result)) {
            context.setResult(new ArrayList<>());
            return;
        }

        // 集合中的字段名称 -> 实体字段名称
        Map<String, String> mapping = context.getDefinition()
                .getFieldDefinitionList()
                .stream()
                .collect(Collectors.toMap(FieldDefinition::getFieldName, FieldDefinition::getFrom));

        // Map转实体
        context.setResult(result.stream()
                .map(item -> {
                    Object bean = BeanUtil.toBean(item, entity, CopyOptions.create()
                            .ignoreError()
                            .ignoreNullValue()
                            .setFieldMapping(mapping)
                            .setTransientSupport(true));

                    // 回写相似度
                    if (bean instanceof SimilaritySetter setter
                            && item instanceof Map<?, ?> map
                            && map.containsKey(MilvusPlusConstants.FIELD_DISTANCE_NAME)) {
                        setter.setSimilarity(Float.parseFloat(String.valueOf(map.get(MilvusPlusConstants.FIELD_DISTANCE_NAME))));
                    }

                    return bean;
                })
                .toList());
    }
}
